const { Schema } = require('koishi')

/**
 * @description 剑网三活动日历插件
 */
class Jx3CalendarPlugin {
  /**
   * @param {object} ctx - Koishi上下文
   * @param {object} config - 插件配置
   */
  constructor(ctx, config) {
    this.ctx = ctx
    this.config = config
    
    // 获取API服务
    this.jx3Api = ctx.jx3Api
    if (!this.jx3Api) {
      throw new Error('请先安装并配置jx3-api插件')
    }
    
    this.registerCommands()
    this.registerSchedule()
  }
  
  /**
   * @description 注册命令
   */
  registerCommands() {
    const { ctx } = this
    
    // 查询今日活动
    ctx.command('jx3.日常', '查询今日活动')
      .action(async ({ session }) => {
        try {
          const activities = await this.jx3Api.getDailyActivities()
          return this.formatDailyActivities(activities)
        } catch (error) {
          ctx.logger.error('查询日常活动失败:', error)
          return `查询失败: ${error.message}`
        }
      })
    
    // 查询周常活动
    ctx.command('jx3.周常', '查询本周活动')
      .action(async ({ session }) => {
        try {
          // 这里假设API同样提供周常活动信息
          // 实际上可能需要单独的API或者本地计算
          const activities = await this.getWeeklyActivities()
          return this.formatWeeklyActivities(activities)
        } catch (error) {
          ctx.logger.error('查询周常活动失败:', error)
          return `查询失败: ${error.message}`
        }
      })
    
    // 查询近期活动
    ctx.command('jx3.活动', '查询近期活动')
      .action(async ({ session }) => {
        try {
          const events = await this.getSpecialEvents()
          return this.formatSpecialEvents(events)
        } catch (error) {
          ctx.logger.error('查询近期活动失败:', error)
          return `查询失败: ${error.message}`
        }
      })
    
    // 活动订阅管理
    ctx.command('jx3.订阅', '管理活动订阅')
      .option('daily', '-d 订阅每日日常提醒', { type: 'boolean' })
      .option('weekly', '-w 订阅每周周常提醒', { type: 'boolean' })
      .option('events', '-e 订阅特殊活动提醒', { type: 'boolean' })
      .option('time', '-t <time:string> 提醒时间 (格式: HH:MM)', { fallback: '08:00' })
      .channelFields(['id'])
      .action(async ({ session, options }) => {
        if (!session.channelId) return '无法识别频道ID'
        
        try {
          // 获取当前订阅设置
          let subscription = await ctx.database.get('jx3_subscription', { channelId: session.channelId })
          
          if (!subscription || subscription.length === 0) {
            // 创建新订阅
            const subId = await ctx.database.create('jx3_subscription', {
              channelId: session.channelId,
              dailyReminder: options.daily || false,
              weeklyReminder: options.weekly || false,
              eventsReminder: options.events || false,
              reminderTime: this.parseTime(options.time || '08:00'),
              createdAt: Date.now()
            })
            
            return `订阅设置成功！
【频道】${session.channelId}
【日常提醒】${options.daily ? '已开启' : '未开启'}
【周常提醒】${options.weekly ? '已开启' : '未开启'}
【活动提醒】${options.events ? '已开启' : '未开启'}
【提醒时间】${options.time || '08:00'}`
          } else {
            // 更新订阅设置
            const currentSub = subscription[0]
            await ctx.database.set('jx3_subscription', { channelId: session.channelId }, {
              dailyReminder: options.daily !== undefined ? options.daily : currentSub.dailyReminder,
              weeklyReminder: options.weekly !== undefined ? options.weekly : currentSub.weeklyReminder,
              eventsReminder: options.events !== undefined ? options.events : currentSub.eventsReminder,
              reminderTime: options.time ? this.parseTime(options.time) : currentSub.reminderTime,
              updatedAt: Date.now()
            })
            
            return `订阅设置已更新！
【频道】${session.channelId}
【日常提醒】${options.daily !== undefined ? (options.daily ? '已开启' : '已关闭') : (currentSub.dailyReminder ? '已开启' : '未开启')}
【周常提醒】${options.weekly !== undefined ? (options.weekly ? '已开启' : '已关闭') : (currentSub.weeklyReminder ? '已开启' : '未开启')}
【活动提醒】${options.events !== undefined ? (options.events ? '已开启' : '已关闭') : (currentSub.eventsReminder ? '已开启' : '未开启')}
【提醒时间】${options.time || this.formatReminderTime(currentSub.reminderTime)}`
          }
        } catch (error) {
          ctx.logger.error('设置活动订阅失败:', error)
          return `设置失败: ${error.message}`
        }
      })
  }
  
  /**
   * @description 注册定时任务
   */
  registerSchedule() {
    const { ctx } = this
    
    // 每天检查日常活动并发送提醒
    ctx.scheduler.cron('0 0 * * *', async () => {
      try {
        // 获取当天日常活动
        const activities = await this.jx3Api.getDailyActivities()
        
        // 获取所有订阅日常提醒的频道
        const subscriptions = await ctx.database.get('jx3_subscription', { dailyReminder: true })
        
        // 为每个频道设置定时提醒
        for (const sub of subscriptions) {
          const triggerTime = new Date(sub.reminderTime)
          const now = new Date()
          
          // 计算今天的提醒时间
          const todayTrigger = new Date(now)
          todayTrigger.setHours(triggerTime.getHours(), triggerTime.getMinutes(), 0, 0)
          
          // 计算延迟时间
          let delay = todayTrigger.getTime() - now.getTime()
          if (delay < 0) {
            // 如果今天的时间已过，不发送提醒
            continue
          }
          
          // 设置延时任务
          setTimeout(async () => {
            try {
              await ctx.bots[0].sendMessage(sub.channelId, this.formatDailyActivities(activities))
            } catch (err) {
              ctx.logger.error('发送日常提醒失败:', err)
            }
          }, delay)
        }
      } catch (error) {
        ctx.logger.error('日常活动提醒任务失败:', error)
      }
    })
    
    // 每周一检查周常活动并发送提醒
    ctx.scheduler.cron('0 0 * * 1', async () => {
      try {
        // 获取本周活动
        const activities = await this.getWeeklyActivities()
        
        // 获取所有订阅周常提醒的频道
        const subscriptions = await ctx.database.get('jx3_subscription', { weeklyReminder: true })
        
        // 为每个频道设置定时提醒
        for (const sub of subscriptions) {
          const triggerTime = new Date(sub.reminderTime)
          const now = new Date()
          
          // 计算今天的提醒时间
          const todayTrigger = new Date(now)
          todayTrigger.setHours(triggerTime.getHours(), triggerTime.getMinutes(), 0, 0)
          
          // 计算延迟时间
          let delay = todayTrigger.getTime() - now.getTime()
          if (delay < 0) {
            // 如果今天的时间已过，不发送提醒
            continue
          }
          
          // 设置延时任务
          setTimeout(async () => {
            try {
              await ctx.bots[0].sendMessage(sub.channelId, this.formatWeeklyActivities(activities))
            } catch (err) {
              ctx.logger.error('发送周常提醒失败:', err)
            }
          }, delay)
        }
      } catch (error) {
        ctx.logger.error('周常活动提醒任务失败:', error)
      }
    })
    
    // 每天检查特殊活动
    ctx.scheduler.cron('0 0 * * *', async () => {
      try {
        // 获取近期特殊活动
        const events = await this.getSpecialEvents()
        
        // 过滤出今天开始的活动
        const today = new Date()
        today.setHours(0, 0, 0, 0)
        
        const tomorrow = new Date(today)
        tomorrow.setDate(tomorrow.getDate() + 1)
        
        const startingEvents = events.filter(event => {
          const startTime = new Date(event.startTime)
          return startTime >= today && startTime < tomorrow
        })
        
        if (startingEvents.length === 0) {
          return
        }
        
        // 获取所有订阅活动提醒的频道
        const subscriptions = await ctx.database.get('jx3_subscription', { eventsReminder: true })
        
        // 为每个频道设置定时提醒
        for (const sub of subscriptions) {
          const triggerTime = new Date(sub.reminderTime)
          const now = new Date()
          
          // 计算今天的提醒时间
          const todayTrigger = new Date(now)
          todayTrigger.setHours(triggerTime.getHours(), triggerTime.getMinutes(), 0, 0)
          
          // 计算延迟时间
          let delay = todayTrigger.getTime() - now.getTime()
          if (delay < 0) {
            // 如果今天的时间已过，不发送提醒
            continue
          }
          
          // 设置延时任务
          setTimeout(async () => {
            try {
              await ctx.bots[0].sendMessage(sub.channelId, this.formatStartingEvents(startingEvents))
            } catch (err) {
              ctx.logger.error('发送活动提醒失败:', err)
            }
          }, delay)
        }
      } catch (error) {
        ctx.logger.error('特殊活动提醒任务失败:', error)
      }
    })
  }
  
  /**
   * @description 获取周常活动（模拟数据）
   * @returns {Promise<object>} 周常活动数据
   */
  async getWeeklyActivities() {
    // 这里应该从API获取周常活动
    // 由于我们没有具体的API，这里返回模拟数据
    return {
      pveDungeon: '荻花宫',
      pvpBattleground: '比武大会',
      weeklyBoss: '世界BOSS-烛龙',
      treasureMaps: ['荒漠山脉', '无量山'],
      challengeTarget: '完成5次荻花宫',
      weekNumber: this.getWeekNumber(),
      updatedAt: Date.now()
    }
  }
  
  /**
   * @description 获取特殊活动（模拟数据）
   * @returns {Promise<Array>} 特殊活动列表
   */
  async getSpecialEvents() {
    // 这里应该从API获取特殊活动
    // 由于我们没有具体的API，这里返回模拟数据
    const now = Date.now()
    const oneDay = 24 * 60 * 60 * 1000
    
    return [
      {
        name: '冬至节庆活动',
        description: '参与各种冬季主题活动，收集特殊货币兑换限定奖励',
        startTime: now + oneDay,
        endTime: now + oneDay * 14,
        rewards: ['冬至时装', '雪人坐骑', '节庆装饰']
      },
      {
        name: '珍·稀世贸易商人',
        description: '珍稀商人到访，提供限定物品交易',
        startTime: now + oneDay * 3,
        endTime: now + oneDay * 5,
        location: '长安城 - 广场'
      },
      {
        name: '双倍经验周',
        description: '所有日常活动获得双倍经验',
        startTime: now + oneDay * 7,
        endTime: now + oneDay * 14
      }
    ]
  }
  
  /**
   * @description 格式化日常活动信息
   * @param {object} activities - 日常活动信息
   * @returns {string} 格式化后的日常活动信息
   */
  formatDailyActivities(activities) {
    const { date, pveDungeon, battleground, commonQuests, teamQuests } = activities
    
    const today = new Date()
    const dateStr = `${today.getFullYear()}年${today.getMonth() + 1}月${today.getDate()}日`
    
    let result = `【剑网三日常 - ${dateStr}】

【PVE日常】${pveDungeon || '暂无数据'}
【PVP日常】${battleground || '暂无数据'}
`
    
    if (commonQuests && commonQuests.length > 0) {
      result += `
【个人日常】`
      commonQuests.forEach(quest => {
        result += `
- ${quest.name}：${quest.description || ''}`
      })
    }
    
    if (teamQuests && teamQuests.length > 0) {
      result += `
      
【团队日常】`
      teamQuests.forEach(quest => {
        result += `
- ${quest.name}：${quest.description || ''}`
      })
    }
    
    return result
  }
  
  /**
   * @description 格式化周常活动信息
   * @param {object} activities - 周常活动信息
   * @returns {string} 格式化后的周常活动信息
   */
  formatWeeklyActivities(activities) {
    const { weekNumber, pveDungeon, pvpBattleground, weeklyBoss, treasureMaps, challengeTarget } = activities
    
    return `【剑网三周常 - 第${weekNumber}周】

【PVE周常】${pveDungeon || '暂无数据'}
【PVP周常】${pvpBattleground || '暂无数据'}
【世界BOSS】${weeklyBoss || '暂无数据'}
【藏宝图】${treasureMaps ? treasureMaps.join('、') : '暂无数据'}
【挑战目标】${challengeTarget || '暂无数据'}`
  }
  
  /**
   * @description 格式化特殊活动信息
   * @param {Array} events - 特殊活动列表
   * @returns {string} 格式化后的特殊活动信息
   */
  formatSpecialEvents(events) {
    if (!events || events.length === 0) {
      return '近期没有特殊活动'
    }
    
    let result = `【剑网三近期活动】

`
    
    events.forEach((event, index) => {
      const startDate = new Date(event.startTime)
      const endDate = new Date(event.endTime)
      
      const startStr = `${startDate.getMonth() + 1}月${startDate.getDate()}日`
      const endStr = `${endDate.getMonth() + 1}月${endDate.getDate()}日`
      
      result += `${index + 1}. 【${event.name}】
   时间：${startStr} - ${endStr}
   ${event.description || ''}
   ${event.location ? `地点：${event.location}` : ''}
   ${event.rewards ? `奖励：${event.rewards.join('、')}` : ''}
   
`
    })
    
    return result
  }
  
  /**
   * @description 格式化即将开始的活动信息
   * @param {Array} events - 活动列表
   * @returns {string} 格式化后的活动信息
   */
  formatStartingEvents(events) {
    let result = `【今日开始的活动】

`
    
    events.forEach((event, index) => {
      const startDate = new Date(event.startTime)
      const endDate = new Date(event.endTime)
      
      const startStr = `${startDate.getMonth() + 1}月${startDate.getDate()}日`
      const endStr = `${endDate.getMonth() + 1}月${endDate.getDate()}日`
      
      result += `${index + 1}. 【${event.name}】今日开始！
   活动时间：${startStr} - ${endStr}
   ${event.description || ''}
   ${event.location ? `地点：${event.location}` : ''}
   ${event.rewards ? `奖励：${event.rewards.join('、')}` : ''}
   
`
    })
    
    return result
  }
  
  /**
   * @description 获取当前是一年中的第几周
   * @returns {number} 周数
   */
  getWeekNumber() {
    const now = new Date()
    const start = new Date(now.getFullYear(), 0, 1)
    const diff = now - start
    const oneWeek = 7 * 24 * 60 * 60 * 1000
    return Math.floor(diff / oneWeek) + 1
  }
  
  /**
   * @description 解析时间字符串为时间戳
   * @param {string} timeStr - 时间字符串 (格式: HH:MM)
   * @returns {number} 时间戳
   */
  parseTime(timeStr) {
    const [hours, minutes] = timeStr.split(':').map(Number)
    
    const date = new Date()
    date.setHours(hours, minutes, 0, 0)
    
    return date.getTime()
  }
  
  /**
   * @description 格式化提醒时间
   * @param {number} timestamp - 时间戳
   * @returns {string} 格式化后的时间字符串
   */
  formatReminderTime(timestamp) {
    const date = new Date(timestamp)
    return `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`
  }
}

// 定义数据库模型
function applyModel(ctx) {
  // 活动订阅
  ctx.model.extend('jx3_subscription', {
    id: 'unsigned',
    channelId: 'string',
    dailyReminder: 'boolean',
    weeklyReminder: 'boolean',
    eventsReminder: 'boolean',
    reminderTime: 'number',
    createdAt: 'number',
    updatedAt: 'number'
  })
}

// 配置模式定义
const configSchema = Schema.object({})

// 插件主方法
module.exports.name = 'jx3-calendar'
module.exports.inject = ['database', 'jx3Api', 'scheduler']

module.exports.Config = configSchema

module.exports.apply = (ctx, config) => {
  // 应用数据库模型
  applyModel(ctx)
  
  // 创建插件实例
  ctx.plugin(Jx3CalendarPlugin, config)
  
  ctx.on('ready', () => {
    ctx.logger.info('剑网三活动日历插件已启动')
  })
} 